#ifndef INTERPRETERHPP
#define INTERPRETERHPP

#include<vector>

#include"parser.hpp"
#include"expression.hpp"
#include"environment.hpp"

class interpreter;

class statement{
public:
	statement(){};
	~statement(){};
	virtual void execute(interpreter* i){};
};

class printStatement:public statement{
public:
	expression* exp;
	printStatement(expression* exp);
	static statement* readStatement(parser* p,interpreter* i);
	void execute(interpreter* i);
};

class declarationStatement:public statement{
public:
	std::string varName;
	expression* exp;
	declarationStatement(std::string varName,expression* exp);
	static statement* readStatement(parser* p,interpreter* i);
	void execute(interpreter* i);
};

class blockStatement:public statement{
public:
	std::vector<statement*> statements;
	blockStatement(decltype(statements) s);
	static statement* readStatement(parser* p,interpreter* i);
	void execute(interpreter* i);
};

class expressionStatement:public statement{
public:
	expression* exp;
	expressionStatement(expression* exp);
	static statement* readStatement(parser* p,interpreter* i);
	void execute(interpreter* i);
};

class interpreter{
private:
	bool haveError;
	int current;
	std::vector<token>* tokens;
	std::vector<statement*> statements;
	environment* innerEnvironment;
public:
	interpreter()=default;
	interpreter(decltype(tokens) tokenList);
	void report(int line,const char* msg);
	void report(int line,std::string& msg);
	void setTokens(decltype(tokens) tokenList);
	void addStatement(statement* s);
	void setGlobalEnvironment();
	statement* getStatement(parser* p);
	void initStatement(parser* p);
	bool atTail();
	void next();
	void prev();
	bool meetSemicolon();
	bool meetEqual();
	bool meetRightBrace();
	int getCurrent();
	int getCurrentLine();
	std::string getCurrentLexeme();
	std::string getCurrentType();
	void define(std::string& name,var* value);
	void enterEnvironment();
	void quitEnvironment();
	var* find(std::string& name);
	void run();
};

#endif